package langnstats.project.languagemodel.ngram;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import langnstats.project.lib.LanguageModel;
import langnstats.project.lib.WordType;
import langnstats.project.lib.clustering.AbstractClusterer;
import langnstats.project.lib.clustering.DummyClusterer;
import langnstats.project.lib.clustering.SuperTypeClusterer;
import langnstats.project.lib.crossvalidation.TrainTokens;
import langnstats.project.tools.CountMap;

public class Ngram implements LanguageModel {

	private static final long serialVersionUID = -4794938345862755410L;
	private int n;
	private NgramAnalysis analysis = null;
//	private NgramCounter<WordType>[] counters;
	private AbstractClusterer clusterer;
	private History<WordType> trainHistory = new History<WordType>();
	private WordType[] allWordType;

	public Ngram(int n){ this(n,new DummyClusterer()); }
	public Ngram(int n, AbstractClusterer clusterer){
		this.n = n;
		this.clusterer = clusterer;
	}
	public Ngram(int n, AbstractClusterer clusterer, NgramAnalysis analysis){
		this.n = n;
		this.clusterer = clusterer;
		this.analysis = analysis;
	}
	
	public AbstractClusterer getClusterer() {
		return clusterer;
	}

	public void setClusterer(AbstractClusterer clusterer) {
		this.clusterer = clusterer;
	}
	
	public double[] predict(WordType wordType) {
		trainHistory.add(wordType);
		trainHistory.trim(n-1);
		
		NgramCounter<WordType> ngramCounter = analysis.getNgramCounter(n);
		CountMap<WordType> countMap = ngramCounter.get(trainHistory);
		
		// maybe need to save probMaps somewhere to avoid recalculation
		Map<WordType,Double> probMap = clusterer.getClusteredProbMap(countMap);
		return WordType.makePredictionArray(probMap);
	}

	public void train(TrainTokens trainTokens) {
		if(this.analysis!=null){ return; }
		
		this.analysis = NgramAnalysis.getAnalysis(trainTokens, n);
	}
	
	public String getDescription(){
		return n+"-gram w/ " + clusterer.getName();
	}

	
	public static List<Ngram> makeAll(int n){
//		NgramAnalysis.analyze(trainTokens, n);
		
		List<Ngram> list = new ArrayList<Ngram>();
		int i=n;
//		for(int i=1; i<=n; i++){
			list.add(new Ngram(i));
			for(SuperTypeClusterer.Type stcType : SuperTypeClusterer.Type.values()){
				list.add(new Ngram(i, new SuperTypeClusterer(stcType)));
			}
//		}
		return list;
	}
	
	public LanguageModel clone(){
		/*LanguageModel model = null;
		try{ model = (LanguageModel)super.clone(); }
		catch(CloneNotSupportedException ex){ throw new RuntimeException(ex); }*/
		return this;
	}
	public void prepare(WordType[] allWordType) {
		// TODO Auto-generated method stub
		
	}

}